package structures.review.link;

import java.util.Stack;

public class SingleLinkListDemo {
    public static void main(String[] args) {
        SingleLinkList<String> singleLinkList = new SingleLinkList<>();
        singleLinkList.add("xinya");
        singleLinkList.add("lisi");
        singleLinkList.add("zhaoliu");
        singleLinkList.list();
        singleLinkList.delete("xinya");
        System.out.println(singleLinkList.contain("xinya"));
        singleLinkList.update("lisi", "wangwu");
        singleLinkList.add("xiaoqi");
        singleLinkList.add("wangba");
        singleLinkList.list();
        System.out.println("-------------");
        singleLinkList.reverse();
        singleLinkList.list();
        System.out.println("-------------");
        singleLinkList.reversePrint();

    }
}

class SingleLinkList<T> {
    private Node<T> head;

    public SingleLinkList() {
        this(null);
    }

    public SingleLinkList(Node<T> head) {
        this.head = head;
    }

    /**
     * 增
     * @param data
     */
    public void add(T data) {
        if (head == null) {
            head = new Node<>(data);
            return;
        }

        Node<T> node = head;
        while (node.getNext() != null) {
            node = node.getNext();
        }
        node.setNext(new Node<T>(data));
    }

    /**
     * 删
     * @param data data
     * @return true/false
     */
    public boolean delete(T data) {
        if (head == null) {
            return false;
        }
        if (head.getData().equals(data)) {
            head = head.getNext();
            return true;
        }
        Node<T> node = head;
        while (node.getNext() != null) {
            if (node.getNext().getData().equals(data)) {
                node.setNext(node.getNext().getNext());
                return true;
            }
        }

        return false;
    }

    /**
     * 改
     * @param data 原data
     * @param data2 修改后的data
     * @return
     */
    public boolean update(T data, T data2) {
        if (head == null) {
            return false;
        }
        Node<T> node = head;
        while (node != null) {
            if (node.getData().equals(data)) {
                node.setData(data2);
                return true;
            }
            node = node.getNext();
        }
        return false;
    }

    /**
     * 查
     * @param data
     * @return
     */
    public boolean contain(T data) {
        Node<T> node = head;
        while (node != null) {
            if (node.getData().equals(data)) {
                return true;
            }
            node = node.getNext();
        }
        return false;
    }

    /**
     * 遍历
     */
    public void list() {
        Node<T> node = head;
        while (node != null) {
            System.out.println(node);
            node = node.getNext();
        }
    }

    /**
     *  单链表翻转
     */
    public void reverse() {
        if (head == null || head.getNext() == null) {
            return;
        }

        Node<T> node = head;
        while (node.getNext() != null) {
            Node<T> nextNode = node.getNext();
            node.setNext(nextNode.getNext());
            nextNode.setNext(head);
            head = nextNode;
        }
    }

    /**
     * 反向打印
     */
    public void reversePrint() {
        Stack<T> stack = new Stack<>();
        Node<T> node = head;
        while (node != null) {
            stack.add(node.getData());
            node = node.getNext();
        }

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }

}

class Node<T> {
    private Object data;
    private Node<T> next;

    public Node(Object data) {
        this.data = data;
    }

    @SuppressWarnings("unchecked")
    public T getData() {
        return (T) data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Node<T> getNext() {
        return next;
    }

    public void setNext(Node<T> next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                '}';
    }
}